# coding: utf-8
from PySide6.QtCore import QPropertyAnimation, QEasingCurve, Property, Qt, Signal, QEvent
from PySide6.QtGui import QEnterEvent
from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout

from .image_label import ImageLabel


class AccordionCard(ImageLabel):
    hovered = Signal(object, bool)
    stretchChanged = Signal(object, float)

    def _postInit(self):
        self.__stretch = 1.0
        self.setRadius(5)
        self.animation = QPropertyAnimation(self, b'stretch', self)
        self.animation.setDuration(200)
        self.animation.setEasingCurve(QEasingCurve.Type.OutQuart)
        self.animation.valueChanged.connect(lambda value: self.stretchChanged.emit(self, value))

        self.setScaledContents(True)

    def getStretch(self) -> float:
        return self.__stretch

    def setStretch(self, stretch: float):
        if self.__stretch == stretch:
            return
        self.__stretch = stretch
        self.updateGeometry()

    def setTargetStretch(self, stretch: float):
        if self.animation.state() == QPropertyAnimation.State.Running:
            self.animation.stop()
        self.animation.setStartValue(self.stretch)
        self.animation.setEndValue(stretch)
        self.animation.start()

    def enterEvent(self, event: QEnterEvent):
        self.hovered.emit(self, True)
        super().enterEvent(event)

    def leaveEvent(self, event: QEvent):
        self.hovered.emit(self, False)
        super().leaveEvent(event)

    stretch = Property(float, getStretch, setStretch)


class AccordionWidget(QWidget):
    def __init__(self, parent=None, orientation=Qt.Orientation.Horizontal):
        super().__init__(parent)
        self._cards = []
        self._cardStretch = {}
        if orientation == Qt.Orientation.Horizontal:
            self.setLayout(QHBoxLayout())
        else:
            self.setLayout(QVBoxLayout())

        self.layout().setContentsMargins(0, 0, 0, 0)

    def addCard(self, card: AccordionCard):
        card.setStretch(1.0)
        card.hovered.connect(self.onCardHovered)
        card.stretchChanged.connect(self.onCardStretchChanged)

        self._cards.append(card)
        self._cardStretch[card] = 1.0
        self.layout().addWidget(card)
        self.updateLayoutStretches()

    def onCardHovered(self, card: AccordionCard, hovered: bool):
        expanded_stretch = 20.0
        default_stretch = 1.0
        if hovered:
            for c in self._cards:
                if c == card:
                    card.setTargetStretch(expanded_stretch)
                else:
                    c.setTargetStretch(default_stretch)
        else:
            for c in self._cards:
                c.setTargetStretch(default_stretch)

    def onCardStretchChanged(self, card: AccordionCard, stretch: float):
        self._cardStretch[card] = stretch
        self.updateLayoutStretches()

    def updateLayoutStretches(self):
        if not self._cards:
            return

        for index, card in enumerate(self._cards):
            layout_stretch = int(self._cardStretch[card] * 1000)
            self.layout().setStretch(index, layout_stretch)

    def count(self):
        return len(self._cards)

    def clear(self):
        while self.layout().count():
            item = self.layout().takeAt(0)
            if item.widget():
                item.widget().deleteLater()
        self._cards.clear()
        self._cardStretch.clear()
